﻿using System;
using System.Runtime.InteropServices;

namespace PlatformInvoke
{
    /// <summary >
    /// This class encapsulates basic functions required
    /// for manage wireless signals in the system.
    /// </summary >
    public class P_Invoke
    {

        #region Functions

        /// <summary>
        /// Opens a connection to the server
        /// </summary>
        /// <param name="dwClientVersion">The highest version of the WLAN API that the client supports</param>
        /// <param name="pReserved">Reserved for future use. Must be set to NULL</param>
        /// <param name="pdwNegotiatedVersion">The version of the WLAN API that will be used in this session. This value is usually the highest version supported by both the client and server</param>
        /// <param name="phClientHandle">A handle for the client to use in this session. This handle is used by other functions throughout the session</param>
        /// <returns>If the function succeeds, the return value is ERROR_SUCCESS (0)</returns>
        [DllImport("wlanapi.dll", SetLastError = true)]
        public static extern UInt32 WlanOpenHandle(UInt32 dwClientVersion,
                IntPtr pReserved, out UInt32 pdwNegotiatedVersion,
                out IntPtr phClientHandle);

        /// <summary>
        /// Closes a connection to the server
        /// </summary>
        /// <param name="hClientHandle">The client's session handle, which identifies the connection to be closed. This handle was obtained by a previous call to the WlanOpenHandle function</param>
        /// <param name="pReserved">Reserved for future use. Set this parameter to NULL</param>
        /// <returns>If the function succeeds, the return value is ERROR_SUCCESS (0)</returns>
        [DllImport("wlanapi.dll", SetLastError = true)]
        public static extern UInt32 WlanCloseHandle(IntPtr hClientHandle,
                                                     IntPtr pReserved);

        /// <summary>
        /// Enumerates all of the wireless LAN interfaces currently enabled on the local computer
        /// </summary>
        /// <param name="hClientHandle">The client's session handle, obtained by a previous call to the WlanOpenHandle function</param>
        /// <param name="pReserved">Reserved for future use. This parameter must be set to NULL</param>
        /// <param name="ppInterfaceList">A pointer to storage for a pointer to receive the returned list of wireless LAN interfaces in a WLAN_INTERFACE_INFO_LIST structure. The buffer for the WLAN_INTERFACE_INFO_LIST returned is allocated by the WlanEnumInterfaces function if the call succeeds</param>
        /// <returns>If the function succeeds, the return value is ERROR_SUCCESS (0)</returns>
        [DllImport("wlanapi.dll", SetLastError = true)]
        public static extern UInt32 WlanEnumInterfaces(IntPtr hClientHandle,
                       IntPtr pReserved, out IntPtr ppInterfaceList);

        /// <summary>
        /// Retrieves the list of available networks on a wireless LAN interface.
        /// </summary>
        /// <param name="clientHandle">The client's session handle, obtained by a previous call to the WlanOpenHandle function</param>
        /// <param name="interfaceGuid">A pointer to the GUID of the wireless LAN interface to be queried. The GUID of each wireless LAN interface enabled on a local computer can be determined using the WlanEnumInterfaces function</param>
        /// <param name="flags">A set of flags that control the type of networks returned in the list. This parameter can be a combination of these possible values:
        /// WLAN_AVAILABLE_NETWORK_INCLUDE_ALL_ADHOC_PROFILES = 0x00000001
        /// WLAN_AVAILABLE_NETWORK_INCLUDE_ALL_MANUAL_HIDDEN_PROFILES = 0x00000002</param>
        /// <param name="reservedPtr">Reserved for future use. This parameter must be set to NULL</param>
        /// <param name="availableNetworkListPtr">A pointer to storage for a pointer to receive the returned list of visible networks in a WLAN_AVAILABLE_NETWORK_LIST structure. The buffer for the WLAN_AVAILABLE_NETWORK_LIST returned is allocated by the WlanGetAvailableNetworkList function if the call succeeds</param>
        /// <returns>If the function succeeds, the return value is ERROR_SUCCESS (0)</returns>
        [DllImport("wlanapi.dll")]
        public static extern int WlanGetAvailableNetworkList(
            IntPtr clientHandle,
            ref Guid interfaceGuid,
            UInt32 flags,
            IntPtr reservedPtr,
            ref IntPtr availableNetworkListPtr);

        /// <summary>
        /// Frees memory. Any memory returned from Native Wifi functions must be freed.
        /// </summary>
        /// <param name="pmemory">Pointer to the memory to be freed</param>
        [DllImport("wlanapi.dll", SetLastError = true)]
        public static extern void WlanFreeMemory(IntPtr pmemory);

        #endregion





        #region Structures

        /// <summary>
        /// This structure contains an array of NIC (Network Interface Controller/Card) information
        /// </summary>
        [StructLayout(LayoutKind.Sequential)]
        public struct WLAN_INTERFACE_INFO_LIST
        {
            // Contains the number of items in the InterfaceInfo member
            public Int32 dwNumberofItems;
            // The index of the current item. The index of the first item is 0. dwIndex must be less than dwNumberOfItems
            public Int32 dwIndex;
            // An array of WLAN_INTERFACE_INFO structures containing interface information
            public WLAN_INTERFACE_INFO[] InterfaceInfo;

            public WLAN_INTERFACE_INFO_LIST(IntPtr pList)
            {
                // The first 4 bytes are the number of WLAN_INTERFACE_INFO structures.
                dwNumberofItems = Marshal.ReadInt32(pList, 0);
                
                // The next 4 bytes are the index of the current item in the unmanaged API.
                dwIndex = Marshal.ReadInt32(pList, 4);

                // Construct the array of WLAN_INTERFACE_INFO structures.
                InterfaceInfo = new WLAN_INTERFACE_INFO[dwNumberofItems];

                for (int i = 0; i < dwNumberofItems; i++)
                {
                    // The offset of the array of structures is 8 bytes past the beginning.
                    // Then, take the index and multiply it by the number of bytes in the
                    // structure.
                    // the length of the WLAN_INTERFACE_INFO structure is 532 bytes - this
                    // was determined by doing a sizeof(WLAN_INTERFACE_INFO) in an
                    // unmanaged C++ app.
                    IntPtr pItemList = new IntPtr(pList.ToInt32() + (i * 532) + 8);

                    // Construct the WLAN_INTERFACE_INFO structure, marshal the unmanaged
                    // structure into it, then copy it to the array of structures.
                    WLAN_INTERFACE_INFO wii = new WLAN_INTERFACE_INFO();
                    wii = (WLAN_INTERFACE_INFO)Marshal.PtrToStructure(pItemList,
                        typeof(WLAN_INTERFACE_INFO));
                    InterfaceInfo[i] = wii;
                }
            }
        }

        /// <summary>
        /// Contains information about a wireless LAN interface
        /// </summary>
        [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
        public struct WLAN_INTERFACE_INFO
        {
            /// Contains the GUID of the interface
            /// GUID->_GUID
            public Guid InterfaceGuid;

            /// Contains the description of the interface
            /// WCHAR[256]
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
            public string strInterfaceDescription;

            /// Contains a WLAN_INTERFACE_STATE value that indicates the current state of the interface
            /// WLAN_INTERFACE_STATE->_WLAN_INTERFACE_STATE
            public WLAN_INTERFACE_STATE isState;
        }

        /// <summary>
        /// Contains an array of information about available networks.
        /// </summary>
        [StructLayout(LayoutKind.Sequential)]
        public struct WLAN_AVAILABLE_NETWORK_LIST
        {
            // Contains the number of items in the Network member
            public UInt32 dwNumberOfItems;
            // The index of the current item. The index of the first item is 0. dwIndex must be less than dwNumberOfItems
            public UInt32 dwIndex;
            // An array of WLAN_AVAILABLE_NETWORK structures containing interface information
            public WLAN_AVAILABLE_NETWORK[] Network;

            public WLAN_AVAILABLE_NETWORK_LIST(IntPtr pList)
            {
                dwNumberOfItems = (uint)Marshal.ReadInt32(pList);
                dwIndex = (uint)Marshal.ReadInt32(pList, 4);
                Network = new WLAN_AVAILABLE_NETWORK[dwNumberOfItems];

                for (int i = 0; i < dwNumberOfItems; i++)
                {
                IntPtr pWlanAvailableNetwork = new IntPtr(pList.ToInt32() + i * Marshal.SizeOf(typeof(WLAN_AVAILABLE_NETWORK)) + 8);
                Network[i] = (WLAN_AVAILABLE_NETWORK)Marshal.PtrToStructure(pWlanAvailableNetwork, typeof(WLAN_AVAILABLE_NETWORK));
                }
            }
        }

        /// <summary>
        /// Contains information about an available wireless network
        /// </summary>
        [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
        public struct WLAN_AVAILABLE_NETWORK
        {
            /// <summary>
            /// Contains the profile name associated with the network. 
            /// If the network does not have a profile, this member will be empty. 
            /// If multiple profiles are associated with the network, there will be multiple entries with the same SSID in the visible network list. 
            /// Profile names are case-sensitive. This string must be NULL-terminated
            /// </summary>
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
            public string profileName;
            /// <summary>
            /// Contains the SSID of the visible wireless network
            /// </summary>
            public DOT11_SSID dot11Ssid;
            /// <summary>
            /// Specifies whether the network is an infrastructure or an ad-hoc one
            /// </summary>
            public DOT11_BSS_TYPE dot11BssType;
            /// <summary>
            /// Indicates the number of BSSIDs in the network
            /// </summary>
            public uint numberOfBssids;
            /// <summary>
            /// Indicates whether the network is connectable or not. If set to TRUE, the network is connectable, otherwise the network cannot be connected to
            /// </summary>
            public bool networkConnectable;
            /// <summary>
            /// Indicates why a network cannot be connected to. This member is only valid when <see cref="networkConnectable"/> is <c>false</c>
            /// </summary>
            public WLAN_REASON_CODE wlanNotConnectableReason;
            /// <summary>
            /// The number of PHY types supported on available networks.
            /// The maximum value of this field is 8. If more than 8 PHY types are supported, <see cref="morePhyTypes"/> must be set to <c>true</c>
            /// </summary>
            private uint numberOfPhyTypes;
            /// <summary>
            /// Contains an array of <see cref="DOT11_PHY_TYPE"/> values that represent the PHY types supported by the available networks.
            /// When <see cref="numberOfPhyTypes"/> is greater than 8, this array contains only the first 8 PHY types.
            /// </summary>
            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
            private DOT11_PHY_TYPE[] dot11PhyTypes;
            /// <summary>
            /// Gets the <see cref="DOT11_PHY_TYPE"/> values that represent the PHY types supported by the available networks
            /// </summary>
            public DOT11_PHY_TYPE[] Dot11PhyTypes
            {
                get
                {
                    DOT11_PHY_TYPE[] ret = new DOT11_PHY_TYPE[numberOfPhyTypes];
                    Array.Copy(dot11PhyTypes, ret, numberOfPhyTypes);
                    return ret;
                }
            }
            /// <summary>
            /// Specifies if there are more than 8 PHY types supported.
            /// When this member is set to <c>true</c>, an application must call <see cref="WlanClient.WlanInterface.GetNetworkBssList"/> to get the complete list of PHY types.
            /// <see cref="WlanBssEntry.phyId"/> contains the PHY type for an entry
            /// </summary>
            public bool morePhyTypes;
            /// <summary>
            /// A percentage value that represents the signal quality of the network.
            /// This field contains a value between 0 and 100.
            /// A value of 0 implies an actual RSSI signal strength of -100 dbm.
            /// A value of 100 implies an actual RSSI signal strength of -50 dbm.
            /// You can calculate the RSSI signal strength value for values between 1 and 99 using linear interpolation
            /// </summary>
            public uint wlanSignalQuality;
            /// <summary>
            /// Indicates whether security is enabled on the network
            /// </summary>
            public bool securityEnabled;
            /// <summary>
            /// Indicates the default authentication algorithm used to join this network for the first time
            /// </summary>
            public DOT11_AUTH_ALGORITHM dot11DefaultAuthAlgorithm;
            /// <summary>
            /// Indicates the default cipher algorithm to be used when joining this network
            /// </summary>
            public DOT11_CIPHER_ALGORITHM dot11DefaultCipherAlgorithm;
            /// <summary>
            /// Contains various flags specifying characteristics of the available network
            /// </summary>
            public UInt32 flags;
            /// <summary>
            /// Reserved for future use. Must be set to NULL
            /// </summary>
            public uint reserved;
        }

        #endregion





        #region Enumerations

        /// <summary>
        /// Interface state enums
        /// </summary>
        public enum WLAN_INTERFACE_STATE : int
        {
            wlan_interface_state_not_ready = 0,
            wlan_interface_state_connected,
            wlan_interface_state_ad_hoc_network_formed,
            wlan_interface_state_disconnecting,
            wlan_interface_state_disconnected,
            wlan_interface_state_associating,
            wlan_interface_state_discovering,
            wlan_interface_state_authenticating
        };

        /// <summary>
        /// Contains the SSID of an interface.
        /// </summary>
        public struct DOT11_SSID
        {
            /// <summary>
            /// The length, in bytes, of the <see cref="SSID"/> array.
            /// </summary>
            public uint SSIDLength;
            /// <summary>
            /// The SSID.
            /// </summary>
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
            public string SSID;
        }

        /// <summary>
        /// Defines a basic service set (BSS) network type.
        /// </summary>
        /// <remarks>
        /// Corresponds to the native <c>DOT11_BSS_TYPE</c> type.
        /// </remarks>
        public enum DOT11_BSS_TYPE
        {
            /// <summary>
            /// Specifies an infrastructure BSS network.
            /// </summary>
            Infrastructure = 1,
            /// <summary>
            /// Specifies an independent BSS (IBSS) network.
            /// </summary>
            Independent = 2,
            /// <summary>
            /// Specifies either infrastructure or IBSS network.
            /// </summary>
            Any = 3
        }

        /// <summary>
        /// Defines reasons for a failure of a WLAN operation.
        /// </summary>
        /// <remarks>
        /// Corresponds to the native reason code identifiers (<c>WLAN_REASON_CODE_xxx</c> identifiers).
        /// </remarks>
        public enum WLAN_REASON_CODE
        {
            Success = 0,
            // general codes
            UNKNOWN = 0x10000 + 1,

            RANGE_SIZE = 0x10000,
            BASE = 0x10000 + RANGE_SIZE,

            // range for Auto Config
            //
            AC_BASE = 0x10000 + RANGE_SIZE,
            AC_CONNECT_BASE = (AC_BASE + RANGE_SIZE / 2),
            AC_END = (AC_BASE + RANGE_SIZE - 1),

            // range for profile manager
            // it has profile adding failure reason codes, but may not have 
            // connection reason codes
            //
            PROFILE_BASE = 0x10000 + (7 * RANGE_SIZE),
            PROFILE_CONNECT_BASE = (PROFILE_BASE + RANGE_SIZE / 2),
            PROFILE_END = (PROFILE_BASE + RANGE_SIZE - 1),

            // range for MSM
            //
            MSM_BASE = 0x10000 + (2 * RANGE_SIZE),
            MSM_CONNECT_BASE = (MSM_BASE + RANGE_SIZE / 2),
            MSM_END = (MSM_BASE + RANGE_SIZE - 1),

            // range for MSMSEC
            //
            MSMSEC_BASE = 0x10000 + (3 * RANGE_SIZE),
            MSMSEC_CONNECT_BASE = (MSMSEC_BASE + RANGE_SIZE / 2),
            MSMSEC_END = (MSMSEC_BASE + RANGE_SIZE - 1),

            // AC network incompatible reason codes
            //
            NETWORK_NOT_COMPATIBLE = (AC_BASE + 1),
            PROFILE_NOT_COMPATIBLE = (AC_BASE + 2),

            // AC connect reason code
            //
            NO_AUTO_CONNECTION = (AC_CONNECT_BASE + 1),
            NOT_VISIBLE = (AC_CONNECT_BASE + 2),
            GP_DENIED = (AC_CONNECT_BASE + 3),
            USER_DENIED = (AC_CONNECT_BASE + 4),
            BSS_TYPE_NOT_ALLOWED = (AC_CONNECT_BASE + 5),
            IN_FAILED_LIST = (AC_CONNECT_BASE + 6),
            IN_BLOCKED_LIST = (AC_CONNECT_BASE + 7),
            SSID_LIST_TOO_LONG = (AC_CONNECT_BASE + 8),
            CONNECT_CALL_FAIL = (AC_CONNECT_BASE + 9),
            SCAN_CALL_FAIL = (AC_CONNECT_BASE + 10),
            NETWORK_NOT_AVAILABLE = (AC_CONNECT_BASE + 11),
            PROFILE_CHANGED_OR_DELETED = (AC_CONNECT_BASE + 12),
            KEY_MISMATCH = (AC_CONNECT_BASE + 13),
            USER_NOT_RESPOND = (AC_CONNECT_BASE + 14),

            // Profile validation errors
            //
            INVALID_PROFILE_SCHEMA = (PROFILE_BASE + 1),
            PROFILE_MISSING = (PROFILE_BASE + 2),
            INVALID_PROFILE_NAME = (PROFILE_BASE + 3),
            INVALID_PROFILE_TYPE = (PROFILE_BASE + 4),
            INVALID_PHY_TYPE = (PROFILE_BASE + 5),
            MSM_SECURITY_MISSING = (PROFILE_BASE + 6),
            IHV_SECURITY_NOT_SUPPORTED = (PROFILE_BASE + 7),
            IHV_OUI_MISMATCH = (PROFILE_BASE + 8),
            // IHV OUI not present but there is IHV settings in profile
            IHV_OUI_MISSING = (PROFILE_BASE + 9),
            // IHV OUI is present but there is no IHV settings in profile
            IHV_SETTINGS_MISSING = (PROFILE_BASE + 10),
            // both/conflict MSMSec and IHV security settings exist in profile 
            CONFLICT_SECURITY = (PROFILE_BASE + 11),
            // no IHV or MSMSec security settings in profile
            SECURITY_MISSING = (PROFILE_BASE + 12),
            INVALID_BSS_TYPE = (PROFILE_BASE + 13),
            INVALID_ADHOC_CONNECTION_MODE = (PROFILE_BASE + 14),
            NON_BROADCAST_SET_FOR_ADHOC = (PROFILE_BASE + 15),
            AUTO_SWITCH_SET_FOR_ADHOC = (PROFILE_BASE + 16),
            AUTO_SWITCH_SET_FOR_MANUAL_CONNECTION = (PROFILE_BASE + 17),
            IHV_SECURITY_ONEX_MISSING = (PROFILE_BASE + 18),
            PROFILE_SSID_INVALID = (PROFILE_BASE + 19),
            TOO_MANY_SSID = (PROFILE_BASE + 20),

            // MSM network incompatible reasons
            //
            UNSUPPORTED_SECURITY_SET_BY_OS = (MSM_BASE + 1),
            UNSUPPORTED_SECURITY_SET = (MSM_BASE + 2),
            BSS_TYPE_UNMATCH = (MSM_BASE + 3),
            PHY_TYPE_UNMATCH = (MSM_BASE + 4),
            DATARATE_UNMATCH = (MSM_BASE + 5),

            // MSM connection failure reasons, to be defined
            // failure reason codes
            //
            // user called to disconnect
            USER_CANCELLED = (MSM_CONNECT_BASE + 1),
            // got disconnect while associating
            ASSOCIATION_FAILURE = (MSM_CONNECT_BASE + 2),
            // timeout for association
            ASSOCIATION_TIMEOUT = (MSM_CONNECT_BASE + 3),
            // pre-association security completed with failure
            PRE_SECURITY_FAILURE = (MSM_CONNECT_BASE + 4),
            // fail to start post-association security
            START_SECURITY_FAILURE = (MSM_CONNECT_BASE + 5),
            // post-association security completed with failure
            SECURITY_FAILURE = (MSM_CONNECT_BASE + 6),
            // security watchdog timeout
            SECURITY_TIMEOUT = (MSM_CONNECT_BASE + 7),
            // got disconnect from driver when roaming
            ROAMING_FAILURE = (MSM_CONNECT_BASE + 8),
            // failed to start security for roaming
            ROAMING_SECURITY_FAILURE = (MSM_CONNECT_BASE + 9),
            // failed to start security for adhoc-join
            ADHOC_SECURITY_FAILURE = (MSM_CONNECT_BASE + 10),
            // got disconnection from driver
            DRIVER_DISCONNECTED = (MSM_CONNECT_BASE + 11),
            // driver operation failed
            DRIVER_OPERATION_FAILURE = (MSM_CONNECT_BASE + 12),
            // Ihv service is not available
            IHV_NOT_AVAILABLE = (MSM_CONNECT_BASE + 13),
            // Response from ihv timed out
            IHV_NOT_RESPONDING = (MSM_CONNECT_BASE + 14),
            // Timed out waiting for driver to disconnect
            DISCONNECT_TIMEOUT = (MSM_CONNECT_BASE + 15),
            // An internal error prevented the operation from being completed.
            INTERNAL_FAILURE = (MSM_CONNECT_BASE + 16),
            // UI Request timed out.
            UI_REQUEST_TIMEOUT = (MSM_CONNECT_BASE + 17),
            // Roaming too often, post security is not completed after 5 times.
            TOO_MANY_SECURITY_ATTEMPTS = (MSM_CONNECT_BASE + 18),

            // MSMSEC reason codes
            //

            MSMSEC_MIN = MSMSEC_BASE,

            // Key index specified is not valid
            MSMSEC_PROFILE_INVALID_KEY_INDEX = (MSMSEC_BASE + 1),
            // Key required, PSK present
            MSMSEC_PROFILE_PSK_PRESENT = (MSMSEC_BASE + 2),
            // Invalid key length
            MSMSEC_PROFILE_KEY_LENGTH = (MSMSEC_BASE + 3),
            // Invalid PSK length
            MSMSEC_PROFILE_PSK_LENGTH = (MSMSEC_BASE + 4),
            // No auth/cipher specified
            MSMSEC_PROFILE_NO_AUTH_CIPHER_SPECIFIED = (MSMSEC_BASE + 5),
            // Too many auth/cipher specified
            MSMSEC_PROFILE_TOO_MANY_AUTH_CIPHER_SPECIFIED = (MSMSEC_BASE + 6),
            // Profile contains duplicate auth/cipher
            MSMSEC_PROFILE_DUPLICATE_AUTH_CIPHER = (MSMSEC_BASE + 7),
            // Profile raw data is invalid (1x or key data)
            MSMSEC_PROFILE_RAWDATA_INVALID = (MSMSEC_BASE + 8),
            // Invalid auth/cipher combination
            MSMSEC_PROFILE_INVALID_AUTH_CIPHER = (MSMSEC_BASE + 9),
            // 802.1x disabled when it's required to be enabled
            MSMSEC_PROFILE_ONEX_DISABLED = (MSMSEC_BASE + 10),
            // 802.1x enabled when it's required to be disabled
            MSMSEC_PROFILE_ONEX_ENABLED = (MSMSEC_BASE + 11),
            MSMSEC_PROFILE_INVALID_PMKCACHE_MODE = (MSMSEC_BASE + 12),
            MSMSEC_PROFILE_INVALID_PMKCACHE_SIZE = (MSMSEC_BASE + 13),
            MSMSEC_PROFILE_INVALID_PMKCACHE_TTL = (MSMSEC_BASE + 14),
            MSMSEC_PROFILE_INVALID_PREAUTH_MODE = (MSMSEC_BASE + 15),
            MSMSEC_PROFILE_INVALID_PREAUTH_THROTTLE = (MSMSEC_BASE + 16),
            // PreAuth enabled when PMK cache is disabled
            MSMSEC_PROFILE_PREAUTH_ONLY_ENABLED = (MSMSEC_BASE + 17),
            // Capability matching failed at network
            MSMSEC_CAPABILITY_NETWORK = (MSMSEC_BASE + 18),
            // Capability matching failed at NIC
            MSMSEC_CAPABILITY_NIC = (MSMSEC_BASE + 19),
            // Capability matching failed at profile
            MSMSEC_CAPABILITY_PROFILE = (MSMSEC_BASE + 20),
            // Network does not support specified discovery type
            MSMSEC_CAPABILITY_DISCOVERY = (MSMSEC_BASE + 21),
            // Passphrase contains invalid character
            MSMSEC_PROFILE_PASSPHRASE_CHAR = (MSMSEC_BASE + 22),
            // Key material contains invalid character
            MSMSEC_PROFILE_KEYMATERIAL_CHAR = (MSMSEC_BASE + 23),
            // Wrong key type specified for the auth/cipher pair
            MSMSEC_PROFILE_WRONG_KEYTYPE = (MSMSEC_BASE + 24),
            // "Mixed cell" suspected (AP not beaconing privacy, we have privacy enabled profile)
            MSMSEC_MIXED_CELL = (MSMSEC_BASE + 25),
            // Auth timers or number of timeouts in profile is incorrect
            MSMSEC_PROFILE_AUTH_TIMERS_INVALID = (MSMSEC_BASE + 26),
            // Group key update interval in profile is incorrect
            MSMSEC_PROFILE_INVALID_GKEY_INTV = (MSMSEC_BASE + 27),
            // "Transition network" suspected, trying legacy 802.11 security
            MSMSEC_TRANSITION_NETWORK = (MSMSEC_BASE + 28),
            // Key contains characters which do not map to ASCII
            MSMSEC_PROFILE_KEY_UNMAPPED_CHAR = (MSMSEC_BASE + 29),
            // Capability matching failed at profile (auth not found)
            MSMSEC_CAPABILITY_PROFILE_AUTH = (MSMSEC_BASE + 30),
            // Capability matching failed at profile (cipher not found)
            MSMSEC_CAPABILITY_PROFILE_CIPHER = (MSMSEC_BASE + 31),

            // Failed to queue UI request
            MSMSEC_UI_REQUEST_FAILURE = (MSMSEC_CONNECT_BASE + 1),
            // 802.1x authentication did not start within configured time 
            MSMSEC_AUTH_START_TIMEOUT = (MSMSEC_CONNECT_BASE + 2),
            // 802.1x authentication did not complete within configured time
            MSMSEC_AUTH_SUCCESS_TIMEOUT = (MSMSEC_CONNECT_BASE + 3),
            // Dynamic key exchange did not start within configured time
            MSMSEC_KEY_START_TIMEOUT = (MSMSEC_CONNECT_BASE + 4),
            // Dynamic key exchange did not succeed within configured time
            MSMSEC_KEY_SUCCESS_TIMEOUT = (MSMSEC_CONNECT_BASE + 5),
            // Message 3 of 4 way handshake has no key data (RSN/WPA)
            MSMSEC_M3_MISSING_KEY_DATA = (MSMSEC_CONNECT_BASE + 6),
            // Message 3 of 4 way handshake has no IE (RSN/WPA)
            MSMSEC_M3_MISSING_IE = (MSMSEC_CONNECT_BASE + 7),
            // Message 3 of 4 way handshake has no Group Key (RSN)
            MSMSEC_M3_MISSING_GRP_KEY = (MSMSEC_CONNECT_BASE + 8),
            // Matching security capabilities of IE in M3 failed (RSN/WPA)
            MSMSEC_PR_IE_MATCHING = (MSMSEC_CONNECT_BASE + 9),
            // Matching security capabilities of Secondary IE in M3 failed (RSN)
            MSMSEC_SEC_IE_MATCHING = (MSMSEC_CONNECT_BASE + 10),
            // Required a pairwise key but AP configured only group keys
            MSMSEC_NO_PAIRWISE_KEY = (MSMSEC_CONNECT_BASE + 11),
            // Message 1 of group key handshake has no key data (RSN/WPA)
            MSMSEC_G1_MISSING_KEY_DATA = (MSMSEC_CONNECT_BASE + 12),
            // Message 1 of group key handshake has no group key
            MSMSEC_G1_MISSING_GRP_KEY = (MSMSEC_CONNECT_BASE + 13),
            // AP reset secure bit after connection was secured
            MSMSEC_PEER_INDICATED_INSECURE = (MSMSEC_CONNECT_BASE + 14),
            // 802.1x indicated there is no authenticator but profile requires 802.1x
            MSMSEC_NO_AUTHENTICATOR = (MSMSEC_CONNECT_BASE + 15),
            // Plumbing settings to NIC failed
            MSMSEC_NIC_FAILURE = (MSMSEC_CONNECT_BASE + 16),
            // Operation was cancelled by caller
            MSMSEC_CANCELLED = (MSMSEC_CONNECT_BASE + 17),
            // Key was in incorrect format 
            MSMSEC_KEY_FORMAT = (MSMSEC_CONNECT_BASE + 18),
            // Security downgrade detected
            MSMSEC_DOWNGRADE_DETECTED = (MSMSEC_CONNECT_BASE + 19),
            // PSK mismatch suspected
            MSMSEC_PSK_MISMATCH_SUSPECTED = (MSMSEC_CONNECT_BASE + 20),
            // Forced failure because connection method was not secure
            MSMSEC_FORCED_FAILURE = (MSMSEC_CONNECT_BASE + 21),
            // ui request couldn't be queued or user pressed cancel
            MSMSEC_SECURITY_UI_FAILURE = (MSMSEC_CONNECT_BASE + 22),

            MSMSEC_MAX = MSMSEC_END
        }

        /// <summary>
        /// Defines an 802.11 PHY and media type.
        /// </summary>
        /// <remarks>
        /// Corresponds to the native <c>DOT11_PHY_TYPE</c> type.
        /// </remarks>
        public enum DOT11_PHY_TYPE : uint
        {
            /// <summary>
            /// Specifies an unknown or uninitialized PHY type.
            /// </summary>
            Unknown = 0,
            /// <summary>
            /// Specifies any PHY type.
            /// </summary>
            Any = Unknown,
            /// <summary>
            /// Specifies a frequency-hopping spread-spectrum (FHSS) PHY. Bluetooth devices can use FHSS or an adaptation of FHSS.
            /// </summary>
            FHSS = 1,
            /// <summary>
            /// Specifies a direct sequence spread spectrum (DSSS) PHY.
            /// </summary>
            DSSS = 2,
            /// <summary>
            /// Specifies an infrared (IR) baseband PHY.
            /// </summary>
            IrBaseband = 3,
            /// <summary>
            /// Specifies an orthogonal frequency division multiplexing (OFDM) PHY. 802.11a devices can use OFDM.
            /// </summary>
            OFDM = 4,
            /// <summary>
            /// Specifies a high-rate DSSS (HRDSSS) PHY.
            /// </summary>
            HRDSSS = 5,
            /// <summary>
            /// Specifies an extended rate PHY (ERP). 802.11g devices can use ERP.
            /// </summary>
            ERP = 6,
            /// <summary>
            /// Specifies the start of the range that is used to define PHY types that are developed by an independent hardware vendor (IHV).
            /// </summary>
            IHV_Start = 0x80000000,
            /// <summary>
            /// Specifies the end of the range that is used to define PHY types that are developed by an independent hardware vendor (IHV).
            /// </summary>
            IHV_End = 0xffffffff
        }

        /// <summary>
        /// Defines a wireless LAN authentication algorithm.
        /// </summary>
        /// <remarks>
        /// Corresponds to the native <c>DOT11_AUTH_ALGORITHM</c> type.
        /// </remarks>
        public enum DOT11_AUTH_ALGORITHM : uint
        {
            /// <summary>
            /// Specifies an IEEE 802.11 Open System authentication algorithm.
            /// </summary>
            IEEE80211_Open = 1,
            /// <summary>
            /// Specifies an 802.11 Shared Key authentication algorithm that requires the use of a pre-shared Wired Equivalent Privacy (WEP) key for the 802.11 authentication.
            /// </summary>
            IEEE80211_SharedKey = 2,
            /// <summary>
            /// Specifies a Wi-Fi Protected Access (WPA) algorithm. IEEE 802.1X port authentication is performed by the supplicant, authenticator, and authentication server. Cipher keys are dynamically derived through the authentication process.
            /// <para>This algorithm is valid only for BSS types of <see cref="DOT11_BSS_TYPE.Infrastructure"/>.</para>
            /// <para>When the WPA algorithm is enabled, the 802.11 station will associate only with an access point whose beacon or probe responses contain the authentication suite of type 1 (802.1X) within the WPA information element (IE).</para>
            /// </summary>
            WPA = 3,
            /// <summary>
            /// Specifies a WPA algorithm that uses preshared keys (PSK). IEEE 802.1X port authentication is performed by the supplicant and authenticator. Cipher keys are dynamically derived through a preshared key that is used on both the supplicant and authenticator.
            /// <para>This algorithm is valid only for BSS types of <see cref="DOT11_BSS_TYPE.Infrastructure"/>.</para>
            /// <para>When the WPA PSK algorithm is enabled, the 802.11 station will associate only with an access point whose beacon or probe responses contain the authentication suite of type 2 (preshared key) within the WPA IE.</para>
            /// </summary>
            WPA_PSK = 4,
            /// <summary>
            /// This value is not supported.
            /// </summary>
            WPA_None = 5,
            /// <summary>
            /// Specifies an 802.11i Robust Security Network Association (RSNA) algorithm. WPA2 is one such algorithm. IEEE 802.1X port authentication is performed by the supplicant, authenticator, and authentication server. Cipher keys are dynamically derived through the authentication process.
            /// <para>This algorithm is valid only for BSS types of <see cref="DOT11_BSS_TYPE.Infrastructure"/>.</para>
            /// <para>When the RSNA algorithm is enabled, the 802.11 station will associate only with an access point whose beacon or probe responses contain the authentication suite of type 1 (802.1X) within the RSN IE.</para>
            /// </summary>
            RSNA = 6,
            /// <summary>
            /// Specifies an 802.11i RSNA algorithm that uses PSK. IEEE 802.1X port authentication is performed by the supplicant and authenticator. Cipher keys are dynamically derived through a preshared key that is used on both the supplicant and authenticator.
            /// <para>This algorithm is valid only for BSS types of <see cref="DOT11_BSS_TYPE.Infrastructure"/>.</para>
            /// <para>When the RSNA PSK algorithm is enabled, the 802.11 station will associate only with an access point whose beacon or probe responses contain the authentication suite of type 2(preshared key) within the RSN IE.</para>
            /// </summary>
            RSNA_PSK = 7,
            /// <summary>
            /// Indicates the start of the range that specifies proprietary authentication algorithms that are developed by an IHV.
            /// </summary>
            /// <remarks>
            /// This enumerator is valid only when the miniport driver is operating in Extensible Station (ExtSTA) mode.
            /// </remarks>
            IHV_Start = 0x80000000,
            /// <summary>
            /// Indicates the end of the range that specifies proprietary authentication algorithms that are developed by an IHV.
            /// </summary>
            /// <remarks>
            /// This enumerator is valid only when the miniport driver is operating in Extensible Station (ExtSTA) mode.
            /// </remarks>
            IHV_End = 0xffffffff
        }

        /// <summary>
        /// Defines a cipher algorithm for data encryption and decryption.
        /// </summary>
        /// <remarks>
        /// Corresponds to the native <c>DOT11_CIPHER_ALGORITHM</c> type.
        /// </remarks>
        public enum DOT11_CIPHER_ALGORITHM : uint
        {
            /// <summary>
            /// Specifies that no cipher algorithm is enabled or supported.
            /// </summary>
            None = 0x00,
            /// <summary>
            /// Specifies a Wired Equivalent Privacy (WEP) algorithm, which is the RC4-based algorithm that is specified in the 802.11-1999 standard. This enumerator specifies the WEP cipher algorithm with a 40-bit cipher key.
            /// </summary>
            WEP40 = 0x01,
            /// <summary>
            /// Specifies a Temporal Key Integrity Protocol (TKIP) algorithm, which is the RC4-based cipher suite that is based on the algorithms that are defined in the WPA specification and IEEE 802.11i-2004 standard. This cipher also uses the Michael Message Integrity Code (MIC) algorithm for forgery protection.
            /// </summary>
            TKIP = 0x02,
            /// <summary>
            /// Specifies an AES-CCMP algorithm, as specified in the IEEE 802.11i-2004 standard and RFC 3610. Advanced Encryption Standard (AES) is the encryption algorithm defined in FIPS PUB 197.
            /// </summary>
            CCMP = 0x04,
            /// <summary>
            /// Specifies a WEP cipher algorithm with a 104-bit cipher key.
            /// </summary>
            WEP104 = 0x05,
            /// <summary>
            /// Specifies a Robust Security Network (RSN) Use Group Key cipher suite. For more information about the Use Group Key cipher suite, refer to Clause 7.3.2.9.1 of the IEEE 802.11i-2004 standard.
            /// </summary>
            WPA_UseGroup = 0x100,
            /// <summary>
            /// Specifies a Wifi Protected Access (WPA) Use Group Key cipher suite. For more information about the Use Group Key cipher suite, refer to Clause 7.3.2.9.1 of the IEEE 802.11i-2004 standard.
            /// </summary>
            RSN_UseGroup = 0x100,
            /// <summary>
            /// Specifies a WEP cipher algorithm with a cipher key of any length.
            /// </summary>
            WEP = 0x101,
            /// <summary>
            /// Specifies the start of the range that is used to define proprietary cipher algorithms that are developed by an independent hardware vendor (IHV).
            /// </summary>
            IHV_Start = 0x80000000,
            /// <summary>
            /// Specifies the end of the range that is used to define proprietary cipher algorithms that are developed by an IHV.
            /// </summary>
            IHV_End = 0xffffffff
        }

        #endregion





        #region Public functions
        /// <summary >
        ///get NIC (Network Interface Card) state  
        /// </summary >
        public static string getStateDescription(WLAN_INTERFACE_STATE state)
        {
            string stateDescription = string.Empty;
            switch (state)
            {
                case WLAN_INTERFACE_STATE.wlan_interface_state_not_ready:
                    stateDescription = "Not ready to operate";
                    break;
                case WLAN_INTERFACE_STATE.wlan_interface_state_connected:
                    stateDescription = "Connected";
                    break;
                case WLAN_INTERFACE_STATE.wlan_interface_state_ad_hoc_network_formed:
                    stateDescription = "First node in an adhoc network";
                    break;
                case WLAN_INTERFACE_STATE.wlan_interface_state_disconnecting:
                    stateDescription = "Disconnecting";
                    break;
                case WLAN_INTERFACE_STATE.wlan_interface_state_disconnected:
                    stateDescription = "Disconnected";
                    break;
                case WLAN_INTERFACE_STATE.wlan_interface_state_associating:
                    stateDescription = "Associating";
                    break;
                case WLAN_INTERFACE_STATE.wlan_interface_state_discovering:
                    stateDescription = "Discovering";
                    break;
                case WLAN_INTERFACE_STATE.wlan_interface_state_authenticating:
                    stateDescription = "Authenticating";
                    break;
            }

            return stateDescription;
        }
        
        #endregion

    }
}